package main

import (
	"encoding/json"
	"fmt"
)

// 结构体声明，类似其他OOP语言的类
//type 结构体名 struct{
//	field1 type
//	field2 type
//	...
//}
type Person struct {
	Name string
	Age int
	Gender string
	Arr [3]int
	ptr *int  // 指针
	slice_ []string  // 切片,切片不能使用匿名方式
	map_ map[string]string  // map
}
// 字段类型可以为基本类型、数组或引用类型
// 结构体创建后，字段没有赋值，则为默认值
// 指针、slice、map默认为nil，还没分配空间.如果使用这些类型，需要make

type Stu struct {
	Name string `json:"name"`  // 定义tag，使得在其他地方使用时可以使用小写name，如 stu := Stu{} stu.name
	Age int `json:"age" valid:"1-100"`  //可以指定多个tag
}

func main() {

	// struct 使用类似其他OOP语言类的实例化
	//var p Person
	// 或者
	p := Person{}
	p.Name = "小明"
	if p.slice_ == nil{
		fmt.Println("yes")
	}
	fmt.Println(p.Name)

	num := 20
	p.ptr = &num

	// 如果切片类型字段赋值，需要make
	p.slice_ = make([]string, 5)
	p.slice_[1] = "go"
	fmt.Println(p)

	// 创建结构体变量的四种方式
	//var p Person
	//var p Person = Person{} || p := Person()
	//var p *Person = new(Person)
	//var p *Person = &Person{}
	p1 := new(Person)  // var p1 Person = new(Person) 或 var p1 *Person = &Person{}
	p1.Name = "golang"  // 底层自动转换为(*p1).Name
	(*p1).Age = 20
	fmt.Println(*p1)
	fmt.Println("-----------")

	stu := Stu{"小明", 18}
	stuJson, err := json.Marshal(stu)
	if err != nil{
		fmt.Println("错误")
	}
	fmt.Println(stuJson, "\n", string(stuJson))

	// 创建结构体实例方法
	// 1. 直接指定
	//var stu1 = Stu{  // 不写字段
	//	"小花",
	//	18,
	//}
	//stu2 := Stu{"小花", 18}
	//var stu3 = Stu{  // 指定字段,不依赖字段定义顺序
	//	Name: "小花",
	//	Age:18,
	//}
	//stu4 := Stu{Name: "小花", Age: 18}

	// 2. 结构体指针类型
	//var stu5 *Stu = &Stu{"小花", 18}  // 不写字段
	//var stu6 := &Stu{"小花", 18}
	//var stu7 = &Stu{  // 指定字段
	//	Name: "小花",
	//	Age:18,
	//}
	//stu8 := &Stu{Name: "小花", Age: 18}

	//判断结构体是否为空
	if stu != (Stu{}){
		fmt.Println("不为空")
	}
}
